package com.tomato.base.dynamic.db.strategy.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * hash 分发 : 基于 HashMap 设计原理
 * 库表总量安装 2 的 n 次幂的方式进行设置，例如 2个库 * 4个表 = 8个表
 * 可以平均分配每个库的数据量和请求压力
 * 扩容会有一个数据迁移的过程，之前的数据需要重新计算 hash 值重新分配到不同的库或表
 * @author lizhifu
 * @date 2022/3/6
 */
public class HashCodeStrategy {
    private Logger logger = LoggerFactory.getLogger(HashCodeStrategy.class);

    public void dynamic(){
        // 分库数量
        int dbCount = 2;
        // 分表数量
        int tbCount = 4;
        // 分库分表字段
        String dynamicKey = "202103050203123345";

        // 学习 HashMap 的原理，类似于整个数组大小为 库数量 *  表数量
        // 整个库表总量为：库数量 *  表数量
        // 2 个库，4 个表，那么总量为 2 * 4 = 8
        int size = dbCount * tbCount;

        // 扰动函数 : 增加随机性，让数据元素更加均匀的散列，减少碰撞
        int idx = (size - 1) & (dynamicKey.hashCode() ^ (dynamicKey.hashCode() >>> 16));

        // idx 即为扰动函数
        // 库1   库2
        // 1111 1111
        // idx 为 3 为库1表3
        // idx 为 7 为库2表3
        int dbIdx = idx / tbCount + 1;
        // 表索引
        int tbIdx = idx - tbCount * (dbIdx - 1);

        logger.info("数据库路由 dbIdx：{} tbIdx：{}",  dbIdx, tbIdx);
    }
}